////////////////////////////////////////////////////////////////////////////////////////////////////
// file:	Equifax.cs
//
// summary:	Implements the equifax class
////////////////////////////////////////////////////////////////////////////////////////////////////

using System;
using System.Collections;
using System.Collections.Specialized;
using System.Data;
using System.Text.RegularExpressions;
using Credit.Objects;
using Microsoft.ApplicationBlocks.ExceptionManagement;
using Dimok.Credit.DSs;
using Config = Dimok.Config;
using Dimok.Credit;

namespace Dimok.Credit
{
	/// <summary>
	/// Summary description for Equifax.
	/// </summary>
	public class Equifax{

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Pull and Parse credit report from EPORT website. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public Equifax(){}
		#region ======== Parse EPORT =======

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Pulls the credit. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="SSN">				. </param>
		/// <param name="firstName">	. </param>
		/// <param name="lastName">		. </param>
		/// <param name="city">				. </param>
		/// <param name="state">			. </param>
		///
		/// <returns>	. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public string[] PullCredit(object SSN,object firstName,object lastName,object city,object state){
			return PullCredit(SSN,firstName,lastName,city,state,"","","");
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Pulls the credit. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="SSN">				. </param>
		/// <param name="firstName">	. </param>
		/// <param name="lastName">		. </param>
		/// <param name="city">				. </param>
		/// <param name="state">			. </param>
		/// <param name="SSN1">				. </param>
		/// <param name="firstName1">	. </param>
		/// <param name="lastName1">	. </param>
		///
		/// <returns>	. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public string[] PullCredit(object SSN,object firstName,object lastName,object city,object state,object SSN1,object firstName1,object lastName1){
			string report = Clients.GetCreditFromEquifax(SSN.ToString(),firstName.ToString(),lastName.ToString(),city.ToString(),state.ToString(),SSN1.ToString(),firstName1.ToString(),lastName1.ToString());
			Match m = Regex.Match(report,@"^(?<r1>[\s\S]+)"+Dimok.Config.Credit.equifax.JointToken+@"(?<r2>[\s\S]+)$",RegexOptions.IgnoreCase);
			return m.Success ? new string[]{m.Groups["r1"].Value,m.Groups["r2"].Value} : new string[]{report};
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Pull and Parse credit report from EPORT website. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="SSN">				. </param>
		/// <param name="firstName">	. </param>
		/// <param name="lastName">		. </param>
		/// <param name="city">				. </param>
		/// <param name="state">			. </param>
		/// <param name="SSN1">				. </param>
		/// <param name="firstName1">	. </param>
		/// <param name="lastName1">	. </param>
		///
		/// <returns>	DataSet with two tables: CreditInfo and TradeAccouns. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public Trades GetCreditInfo(object SSN,object firstName,object lastName,object city,object state,object SSN1,object firstName1,object lastName1){
			return GetCreditInfo(PullCredit(SSN,firstName,lastName,city,state,SSN1,firstName1,lastName1));
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Parse credit report from string. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="textReport">	The text report. </param>
		///
		/// <returns>	DataSet with two tables: CreditInfo and TradeAccouns. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public Trades GetCreditInfo(string textReport){return GetCreditInfo(new string[]{textReport});}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Parse credit report from string. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="textReports">	The text reports. </param>
		///
		/// <returns>	DataSet with two tables: CreditInfo and TradeAccouns. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public Trades GetCreditInfo(string[] textReports){
			//CheckReportError(textReport);
			Trades trades = new Trades();
			for( int i=0; i < textReports.Length; i++ ){
				string textReport = Regex.Replace(textReports[i],@"\n\s*\n\s*\n","\n\n",RegexOptions.Compiled);
				Trades.t_CreditInfoRow drCrInf = trades.t_CreditInfo.Newt_CreditInfoRow();
				drCrInf.PrevBankruptcy = 0;
				drCrInf.DatePulled = DateTime.Now;
				drCrInf.HumanReadable = textReport;
				if( trades.t_Applicants.Count == 0 ){
					DateTime since = GetSubjectsInfo(trades.t_Applicants,textReport);
					if( since != DateTime.Today )drCrInf.TimeInBureauDate = since;
					GetBankruptcy(drCrInf,string.Join("\n",textReports));
					drCrInf.CreditReport = parseAccounts(trades,string.Join("\n",textReports));
					drCrInf.IsaacScore = GetBEACON(textReport);
				}
				trades.t_CreditInfo.Addt_CreditInfoRow(drCrInf);
			}
			return trades;
		}
		#region Subject Info ==================

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Gets a beacon. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="textReport">	The text report. </param>
		///
		/// <returns>	The beacon. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		private int GetBEACON(string textReport) {
			Match m = Regex.Match(textReport, "BEACON 5.0 SCORE:\\s*(\\d+)");
			return int.Parse("0" + m.Groups[1].Value);
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Gets the subjects information. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="dtAppl">			The dt appl. </param>
		/// <param name="textReport">	The text report. </param>
		///
		/// <returns>	The subjects information. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		private DateTime GetSubjectsInfo(Trades.t_ApplicantsDataTable dtAppl,string textReport){
			MatchCollection mcSubject  = Regex.Matches(textReport,@"[*](?<ln>\w+),(?<fn>\w+).+?SINCE\s+(?<since>[\d/]+)\s+FAD\s.+?FN-[\s\S]*?[\n|\r][*]");
			if( mcSubject.Count == 0 )return DateTime.Today;
			GetSubjectInfo(dtAppl,mcSubject[0]);
			if( mcSubject.Count > 1 )GetSubjectInfo(dtAppl,mcSubject[1]);
			try{return DateTime.Parse(mcSubject[0].Groups["since"].Value);
			}catch(Exception){return DateTime.Today;}
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Gets a subject information. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="dtAppl">		The dt appl. </param>
		/// <param name="mSubject">	The subject. </param>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		private void GetSubjectInfo(Trades.t_ApplicantsDataTable dtAppl,Match mSubject){
			Trades.t_ApplicantsRow rowAppl = dtAppl.Newt_ApplicantsRow();
			//rowAppl.LastName = mSubject.Groups["ln"].Value;
			rowAppl.FirstName = mSubject.Groups["fn"].Value;
			Match mPhone = Regex.Match(mSubject.Value,@"TELEPHONE NUMBER\s+(?<ph>\(?\d{3}\)?\s+\d{3}-\d{4})\s+SPEC\s+");
			if( mPhone.Success )
				rowAppl.HomePhone = decimal.Parse(Regex.Replace(mPhone.Groups["ph"].Value,"\\D",""));
			GetBDS(rowAppl,mSubject);
			GetAddress((Trades)dtAppl.DataSet,mSubject);
			dtAppl.Addt_ApplicantsRow(rowAppl);
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Gets the address. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="report">	The report. </param>
		///
		/// <returns>	The address. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static Match GetAddress(string report){
			Match mSubject  = Regex.Match(report,@"[*](?<ln>\w+),(?<fn>\w+).+?SINCE\s+(?<since>[\d/]+)\s+FAD\s.+?FN-[\s\S]*?\n\s*(?<address>.*)");
			return Regex.Match(mSubject.Groups["address"].Value,@"(?<street>.+),.{3,}?,(?<state>\w\w),(?<zip>\d{5})");
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Gets the address. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="trades">		The trades. </param>
		/// <param name="mSubject">	The subject. </param>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		private void GetAddress(Trades trades,Match mSubject){
			string[] address = mSubject.Value.Split('\n');
			for( int i = 1; i < 3; i++ ){
				Match mAddress = Regex.Match(address[i],@"(?<street>.+),(?<city>.{3,}?),(?<state>\w\w),(?<zip>\d{5})");;
				if( !mAddress.Success )continue;
				Trades.t_AddressRow rowAddress = trades.t_Address.Newt_AddressRow();
				rowAddress.ApplicantID = trades.t_Address.Count;
				rowAddress.Years = rowAddress.Months =	0;
				rowAddress.Index = (byte)trades.t_Address.Count;
				rowAddress.Street = mAddress.Groups["street"].Value.Trim();
				rowAddress.CityName = mAddress.Groups["city"].Value.Trim();
				rowAddress.StateCode = mAddress.Groups["state"].Value.Trim();
				rowAddress.Zip = mAddress.Groups["zip"].Value.Trim();
				trades.t_Address.Addt_AddressRow(rowAddress);
			}
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Gets the bds. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="rowAppl">	The row appl. </param>
		/// <param name="mSubject">	The subject. </param>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		private void GetBDS(Trades.t_ApplicantsRow rowAppl, Match mSubject){
			Match mBDS = Regex.Match(mSubject.Value,@"[\n\r]\s+BDS-(?<bds>[\d/]+)");
			string text = mBDS.Groups["bds"].Value;
			string[] bds = text.Split('/');
			if( bds.Length == 3 ){
				rowAppl.DOBMonth = Math.Min(12,Math.Max(int.Parse(bds[0]),1));
				rowAppl.DOBDay = Math.Min(31,Math.Max(int.Parse(bds[1]),1));
				rowAppl.DOBYear = int.Parse(bds[2]);
			}
		}
		#endregion Subject Info ==================

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Check report error. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <exception cref="CreditReportException">	Thrown when creditreport. </exception>
		///
		/// <param name="textReport">	The text report. </param>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static void CheckReportError(string textReport){
			Match mMan = Regex.Match(textReport,@"[\s\S]*"+Dimok.Config.Credit.equifax.JointToken,RegexOptions.IgnoreCase|RegexOptions.RightToLeft);
			string sMan = textReport,sWife = "";
			if( mMan.Success ){
				sMan = mMan.Value;
				sWife = Regex.Match(textReport,Dimok.Config.Credit.equifax.JointToken+@"[\s\S]*",RegexOptions.IgnoreCase).Value;
			}
			if( Regex.IsMatch(sMan,Dimok.Config.Credit.equifax.ErrorToken,RegexOptions.IgnoreCase) )throw new CreditReportException(sMan);
			if( Regex.IsMatch(sWife,Dimok.Config.Credit.equifax.ErrorToken,RegexOptions.IgnoreCase) )throw new CreditReportException(sWife);
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Query if 'textReport' is joint. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="textReport">	The text report. </param>
		///
		/// <returns>	true if joint, false if not. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		private bool IsJoint(string textReport){
			return Regex.IsMatch(textReport,Dimok.Config.Credit.equifax.JointToken,RegexOptions.IgnoreCase) ||
						 Regex.Matches(textReport,"SAFESCANNED ").Count > 1;
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Gets a bankruptcy. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <exception cref="CreditReportException">	Thrown when creditreport. </exception>
		///
		/// <param name="rowCrInf">		The row carriage return inf. </param>
		/// <param name="textReport">	The text report. </param>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		private void GetBankruptcy(Trades.t_CreditInfoRow rowCrInf,string textReport){
			//string FILTER_CLOSED = new RegExp("(DSMSD|DESMSD|DISMSD|DSCHG|DESCHG|DISCHG)","i");
			try{
				bool isJoint = IsJoint(textReport);
				MatchCollection mcPublic = Regex.Matches(textReport, @"(?<=\n)[*]{2,}.+public.+[*]{2,}.+([\s\S]+?\n.*)[*]{5,}",RegexOptions.IgnoreCase|RegexOptions.Compiled);
				rowCrInf.OpenBankruptcy = false;
				rowCrInf.PrevBankruptcy = rowCrInf.BK_7_Count = rowCrInf.BK_13_Count = 0;
				if( isJoint )rowCrInf.BK_Joint = false; // both must have the same last BK
				else rowCrInf.SetBK_JointNull();
				if( mcPublic.Count > 0 ){
					Match mPublic = mcPublic[0];
					Regex reNextLine = new Regex(@"[ \r]+\n[ ]+");
					string pubRecs = reNextLine.Replace(mcPublic[0].Groups[1].Value,"",1);
					pubRecs += "\n";
					MatchCollection mcBKs = Regex.Matches(pubRecs,@"(?<=\n\d\d)[\s\S]+?(?<date>\d\d/\d\d)[\s\S]+?CH-(?<ch>\d{1,2})[\s\S]+?(?=\n\S?)",RegexOptions.Compiled);
					foreach( Match mBK in mcBKs ){
						DateTime BKDate = DateTime.Parse(GetDateCreditStyle(mBK.Groups["date"].Value));
						switch(mBK.Groups["ch"].Value){
							case  "7":
								if( rowCrInf.IsBK_7_DateNull() || rowCrInf.BK_7_Date < BKDate ){
									rowCrInf.BK_7_Date  = BKDate;
									rowCrInf.BK_7_Dismissed = Regex.IsMatch(mBK.Value,"(DSMSD|DESMSD|DISMSD)",RegexOptions.Compiled);
									if( isJoint )rowCrInf.BK_Joint = mcPublic.Count > 1 && mcPublic[1].Value.IndexOf(mBK.Value) >= 0;
								}
								rowCrInf.BK_7_Count++;
								break;
							case "13":
								if( rowCrInf.IsBK_13_DateNull() || rowCrInf.BK_13_Date < BKDate )
									rowCrInf.BK_13_Date  = BKDate;
								rowCrInf.BK_13_Count++;
								break;
							case "12": break;
							case "11": break;
							default: throw new CreditReportException("Unknown bankruptcy chapter - ["+mBK.Groups["ch"].Value+"].");
						}
					}
					if( rowCrInf.BK_7_Count == 0 ){
						Match mBK7 = Regex.Match(textReport,@"BANKRUPTCY\s+CHAPTER\s+7");
						if( mBK7.Success )rowCrInf.BK_7_Count = 1;
					}
					if( rowCrInf.BK_7_Count > 0 )
						rowCrInf.PrevBankruptcy =	7;
					else if( rowCrInf.BK_13_Count > 0 )
						rowCrInf.PrevBankruptcy =	13;
					//var FILTER_BK = new RegExp("\\WCH-\\d{1,2}","i");
					//s = s[1].replace(/\n(\d{2})/g,"\n\n$1");
					//s = s.split("\n\n");
					//for( var i=0; i < s.length; i++ )
					//	if( s[i].match(FILTER_BK) ){
					//		try{rsCI_BankruptcyDate(s[i].match(/^\d{2} (\d\d\/\d\d)/)[1].replace(/[/]/,"/01/"));}catch(e){}
					//		///if( !s[i].match(FILTER_CLOSED) )rsCI_OpenBankruptcy(true);
					//		var a = s[i].replace(/\s*\n\s*/g,"").match(/ch-(\d{1,2})/i);
					//		if( a )rsCI_PrevBankruptcy(a[1]);
					//		return;
					//	}
				}
				//if( !textReport.match(/BANKRUPTCY/i) )return;
				//var ch = textReport.match(/CHAPTER\s+(\d{1,2})/i);
				//if( !ch )return rsCI_PrevBankruptcy(1);
				//rsCI_PrevBankruptcy(ch[1]);
			}catch(Exception exc){
				NameValueCollection nvc = new NameValueCollection();
				nvc.Add("Report","\n"+textReport+"\n");
				ExceptionManager.Publish(exc,nvc);
			}
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Gets a date credit style. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="text">	The text. </param>
		///
		/// <returns>	The date credit style. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		private string GetDateCreditStyle(string text){return text.Replace("/","/01/");}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Decode fax field. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="text">	The text. </param>
		///
		/// <returns>	. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		private object decodeEFaxField(string text){
			text = text.Trim();
			if( text.Length <= 6 ){
				Match m = Regex.Match(text,@"^(\d{2})\/(\d{2})",RegexOptions.Compiled);
				if( m.Groups.Count == 3 )return m.Groups[1].Value+"/01/"+m.Groups[2].Value; // It's a date
				text = Regex.Replace(text,@"^(?<thou>\d+)K$","${thou}000",RegexOptions.IgnoreCase | RegexOptions.Compiled);
				text = Regex.Replace(text,@"^(?:\d+M|[+])","",RegexOptions.IgnoreCase | RegexOptions.Compiled);//Term shows months, delete it.
			}
			return text == "" ? (object)System.DBNull.Value : text;
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Check accounts. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="tdTrades">	The td trades. </param>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		private void CheckAccounts(Trades.t_TradeReferencesDataTable tdTrades){
			for( int i=0; i < tdTrades.Rows.Count; i++ ){
				Trades.t_TradeReferencesRow row = (Trades.t_TradeReferencesRow)tdTrades.Rows[i];
				if( IsUnwantedTrade(row) ){
					row.Delete();
					i--;
					continue;
				}
				if( !row.IsAccountDescNull() && row.AccountDesc != "" ){
					string desc = row.AccountDesc;
					if( Regex.IsMatch(desc,"(?:SECURED|CREDIT LINE)",RegexOptions.Compiled | RegexOptions.IgnoreCase) )row.AccType = "I";
					if( Regex.IsMatch(desc,"credit card",RegexOptions.Compiled | RegexOptions.IgnoreCase) )row.AccType = "R";
					if( Regex.IsMatch(desc,"FORECLOSURE",RegexOptions.Compiled | RegexOptions.IgnoreCase) )row.Status = 9;
				}
			}
			RemoveDuplicates(tdTrades);
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Removes the duplicates described by tdTrades. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="tdTrades">	The td trades. </param>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		private void RemoveDuplicates(Trades.t_TradeReferencesDataTable tdTrades){
			try{
				DataSet ds = tdTrades.DataSet;
				Trades.t_TradeReferencesDataTable dtParent = (Trades.t_TradeReferencesDataTable)tdTrades.Copy();
				dtParent.TableName = "DupsParent";
				ds.Tables.Add(dtParent);
				DataRelation rel = ds.Relations.Add( "Dups",new DataColumn[]{dtParent.FirmCodeColumn,dtParent.OpenDateColumn,dtParent.HighCreditColumn,dtParent.TermColumn},new DataColumn[]{tdTrades.FirmCodeColumn,tdTrades.OpenDateColumn,tdTrades.HighCreditColumn,tdTrades.TermColumn},false);
				dtParent.Columns.Add("Counter",typeof(int),"COUNT(Child.FirmCode)");
				DataView dvParent = dtParent.DefaultView;
				dvParent.RowFilter = "Counter>1";
				while( dvParent.Count > 0 ){
					DataView dvTrades = dvParent[0].CreateChildView(rel);
					dvTrades.Sort = "MR DESC,ReportDate DESC,HighCredit DESC";
					while( dvTrades.Count > 1 )
						dvTrades[dvTrades.Count-1].Row.Delete();
					dvTrades.Table.AcceptChanges();
					dvParent[0].Row.Delete();
				}
				ds.Relations.Remove(rel);
				ds.Tables.Remove(dtParent);
			}catch(Exception exc){
				NameValueCollection nvc = new NameValueCollection();
				nvc.Add("!!!!!","!!!!!");
				ExceptionManager.Publish(exc,nvc);
			}
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Query if 'row' is unwanted trade. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="row">	The row. </param>
		///
		/// <returns>	true if unwanted trade, false if not. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		private bool IsUnwantedTrade(Trades.t_TradeReferencesRow row){
			return IsStudentLoan(row) ||
				!row.IsECOANull() && row.ECOA.ToLower().IndexOfAny(new char[]{'a','u'}) >= 0 ||
				!row.IsAccTypeNull() && row.AccType.ToLower().IndexOf("o") >= 0 ||
				row.IsStatusNull();
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Query if 'row' is student loan. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="row">	The row. </param>
		///
		/// <returns>	true if student loan, false if not. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		private bool IsStudentLoan(Trades.t_TradeReferencesRow row){
			Regex reStLoan = new Regex("(?:FFELP|STUDNT LN)",RegexOptions.IgnoreCase | RegexOptions.Compiled);
			return !row.IsAccountDescNull() && row.AccountDesc.ToLower().IndexOf("student") >=0 ||
				!row.IsFirmCodeNull() &&	reStLoan.IsMatch(row.FirmCode);

		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Gets a history. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="row">	The row. </param>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		private void GetHistory(Trades.t_TradeReferencesRow row){
			Match mDD = Regex.Match(row.AccountDesc,@"30\((\d\d)\)60\((\d\d)\)90[+]\((\d\d)\) (.*?\d\d\/\d\d-[IR]\d)");
			if( !mDD.Success )return;
			row._30_ = byte.Parse(mDD.Groups[1].Value);
			row._60_ = byte.Parse(mDD.Groups[2].Value);
			row._90_ = byte.Parse(mDD.Groups[3].Value);
			string[] saDDs = mDD.Groups[4].Value.Split(',');
			for( int i=0; i < saDDs.Length; i++ ){
				row["DD"+(i+1)] = saDDs[i].Split('-')[0].Replace("/","/01/");
				row["DS"+(i+1)] = saDDs[i].Split('-')[1].Substring(1);
			}
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Parse accounts. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="trades">			The trades. </param>
		/// <param name="textReport">	The text report. </param>
		///
		/// <returns>	. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		private string parseAccounts(Trades trades,string textReport){
			textReport = Regex.Replace(textReport,@"\n\n[*]","\n&\n*");
			textReport = Regex.Replace(textReport,@"\\","_");
			textReport = Regex.Replace(textReport,@"&\s+\n","\n&");
			MatchCollection mcTrades = Regex.Matches(textReport,@"(?<=\n)(.{10}[* ]\d{3}[^\s\d]{2}[\d ]{5} \d\d/\d\d.+)(?<desc>[\s\S]+?)(?=\n\S|.{10}[*])");
			ArrayList alTrades = new ArrayList();
			foreach( Match mTrade in mcTrades ){
				alTrades.Add(mTrade.Value);
				if( Regex.IsMatch(mTrade.Value,"BANKRUPTCY",RegexOptions.IgnoreCase | RegexOptions.Compiled) )continue;
				Match m1 = 	Regex.Match(mTrade.Value,"^(?<FirmCode>.{0,10})..{3}(?<IndustryCode>\\w{0,2}).{0,5}(?<ReportDate>.{0,6})(?<OpenDate>.{0,6})(?<HighCredit>.{0,5})(?<Term>.{0,4})(?<Ballance>.{0,5})(?<PastDue>.{0,4})(?<AccType>.{0,2})(?<Status>.{1})(?<MR>.{0,3})(?<ECOA>.{0,2})(?<AccNumber>.+)");
				Trades.t_TradeReferencesRow newRow = trades.t_TradeReferences.Newt_TradeReferencesRow();
				foreach( DataColumn col in trades.t_TradeReferences.Columns )
					try{
						if( m1.Groups[col.ColumnName].Value != "" )newRow[col.ColumnName] = decodeEFaxField(m1.Groups[col.ColumnName].Value);
					}catch(Exception){
						//
					}
				if( newRow.IsHighCreditNull() && newRow.IsBallanceNull() )continue;
				newRow.DatePulled = DateTime.Now;
				if( newRow["Term"] == System.DBNull.Value )newRow.Term = 0;
				string desc = mTrade.Groups["desc"].Value.Replace("\n","");
				newRow.AccountDesc = desc.Trim();
				Match mDLA = Regex.Match(desc,@"DLA\s(\d{2}\/\d{2})");
				if( mDLA.Success )newRow.LastDate = DateTime.Parse(decodeEFaxField(mDLA.Groups[1].Value).ToString());
				GetHistory(newRow);
				trades.t_TradeReferences.Addt_TradeReferencesRow(newRow);
			}
			CheckAccounts(trades.t_TradeReferences);
			return string.Join(Environment.NewLine,(string[])alTrades.ToArray(typeof(string)))+Environment.NewLine;
		}
		#endregion ======== Parse EPORT =======

	}
}
